#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include "socket.h"

#define BACKLOG 200

int create_listener_socket (unsigned short port)
{
	int sd;
	int option = 1;
	struct sockaddr_in sin;

	/* Create socket. */
	if ((sd = socket (PF_INET, SOCK_STREAM, 0)) < 0) {
		return -1;
	}

	/* Make listener socket non-blocking. */
	if (setnonblocking (sd) < 0) {
		close (sd);
		return -1;
	}

	/* Reuse address. */
	if (setsockopt (sd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof (int)) < 0) {
		close (sd);
		return -1;
	}

	/* Fill struct sockaddr_in. */
	sin.sin_family = PF_INET;
	sin.sin_addr.s_addr = htonl (INADDR_ANY);
	sin.sin_port = htons (port);
	memset (&(sin.sin_zero), 0, 8);

	/* Bind. */
	if (bind (sd, (struct sockaddr *) &sin, sizeof (struct sockaddr)) < 0) {
		close (sd);
		return -1;
	}

	/* Listen. */
	if (listen (sd, BACKLOG) < 0) {
		close (sd);
		return -1;
	}

	return sd;
}

int setnonblocking (int fd)
{
	int flags;

	flags = fcntl (fd, F_GETFL);
	flags |= O_NONBLOCK;
	if (fcntl (fd, F_SETFL, flags) < 0) {
		return -1;
	}

	return 0;
}
